using System;
using System.Collections.Generic;
using System.Text;

using WozLib.UI.Ink.SketchCommands;
using WozLib.UI.Ink.SketchObjects;

namespace WozLib.UI.Ink.SketchProperties
{
  public class CascadingProperty
  {

    public SketchProperty WozProperty
    {
      get { return _WozProperty; }
      set { _WozProperty = value; }
    } private SketchProperty _WozProperty;

    public List<ISketchObject> IWozObjects
    {
      get { return _IWozObjects; }
      set { _IWozObjects = value; }
    } private List<ISketchObject> _IWozObjects;

    public List<SketchProperty> WozPropertyVariants
    {
      get { return _WozPropertyVariants; }
      set { _WozPropertyVariants = new List<SketchProperty>(value); }
    } private List<SketchProperty> _WozPropertyVariants;

    public string Description
    {
      get
      {
        if (WozProperty != null)
        {
          return WozProperty.ToString();
        }
        else
        {
          return "CascadingProperty";
        }
      }
    }

    public CascadingProperty()
    {
    }

    public CascadingProperty(List<ISketchObject> iWozObjects, SketchProperty wozProperty)
    {
      IWozObjects = iWozObjects;
      WozProperty = wozProperty;
      wozProperty.WozPropertyChanged += new WozLib.UI.Ink.SketchProperties.SketchProperty.WozPropertyChangedDelegate(wozProperty_WozPropertyChanged);

      List<SketchProperty> variants = new List<SketchProperty>();

      foreach (ISketchObject iWozObject in IWozObjects)
      {
        SketchProperty wp = iWozObject.GetProperty(wozProperty.WozPropertyType);

        if (!variants.Contains(wp))
        {
          variants.Add(wp);
        }
      }

      this.WozPropertyVariants = variants;
    }

    public delegate void CommandOccuredDelegate(SketchCommand wozClientCommand);

    public event CommandOccuredDelegate CommandOccured;

    public event CommandOccuredDelegate ContinuousCommandOccured;


    public bool InContinuousChange
    {
      get 
      {
        return _InContinuousChange; 
      }
      set 
      {
        if (_InContinuousChange != value)
        {
          _InContinuousChange = value;
          if (_InContinuousChange)
          {
            StartContinuousChange();
          }
          else
          {
            StopContinuousChange();
          }
        }
      }
    } private bool _InContinuousChange;

    List<SketchObject> _previousWozObjects;
    private void StartContinuousChange()
    {
      // start packaging up the changes (or just store the starting state)
      _previousWozObjects = new List<SketchObject>();

      foreach (ISketchObject iWozObject in IWozObjects)
      {
        SketchObject previousWozObject = new SketchObject(
          iWozObject.WozID, iWozObject.GetProperty(WozProperty.WozPropertyType).Clone() as SketchProperty);
        _previousWozObjects.Add(previousWozObject);
      }
    }

    private void StopContinuousChange()
    {
      // package up final value with initial value and send of as a command for undo/redo
      List<SketchObject> newWozObjects = new List<SketchObject>();

      foreach (ISketchObject iWozObject in IWozObjects)
      {
        SketchObject newWozObject = new SketchObject(iWozObject.WozID, WozProperty.Clone() as SketchProperty);
        newWozObjects.Add(newWozObject);
      }

      // create a modify command based on this property changing to the new value
      ModifyObjectSketchCommand wozModifyObjectCommand = new ModifyObjectSketchCommand(newWozObjects, _previousWozObjects);

      if (CommandOccured != null)
      {
        CommandOccured(wozModifyObjectCommand);
      }
    }

    void wozProperty_WozPropertyChanged(SketchProperty wozProperty)
    {
      List<SketchObject> previousWozObjects = new List<SketchObject>();

      List<SketchObject> newWozObjects = new List<SketchObject>();

      foreach (ISketchObject iWozObject in IWozObjects)
      {
        SketchObject previousWozObject = new SketchObject(
          iWozObject.WozID, iWozObject.GetProperty(wozProperty.WozPropertyType).Clone() as SketchProperty);
        previousWozObjects.Add(previousWozObject);

        SketchObject newWozObject = new SketchObject(iWozObject.WozID, wozProperty.Clone() as SketchProperty);
        newWozObjects.Add(newWozObject);
      }

      // create a modify command based on this property changing to the new value
      ModifyObjectSketchCommand wozModifyObjectCommand = new ModifyObjectSketchCommand(newWozObjects, previousWozObjects);

      if (InContinuousChange && ContinuousCommandOccured != null)
      {
        ContinuousCommandOccured(wozModifyObjectCommand);
      }
      else if (!InContinuousChange && CommandOccured != null)
      {
        CommandOccured(wozModifyObjectCommand);
      }
    }
  }
}
